package pkg;
/**
 * BomberBoy, CPS240 Term Project - Team A
 * Andrew Osterink, David Bash, Scott Kidder
 * 
 * Generic dispatch system. This is the core of all dispatch systems
 * and can easily be assigned to different tasks.
 * To Note: order of objects when the event is being fired dosn't matter.
 */
import java.util.Hashtable;

public class Dispatcher<T> {
	Hashtable<DispatchPair,DispatchAction<T>> map;
	
	public Dispatcher()
	{
		map = new Hashtable<DispatchPair,DispatchAction<T>>();
	}
	
	
	/**
	 * Executes specified action if an event is fired using c
	 * lass 1 and class 2.
	 */
	@SuppressWarnings("unchecked")
	public void register(Class type1,Class type2,DispatchAction<T> action)
	{
		register(type1.getName(),type2.getName(), action);
	}
	
	/**
	 *  Shouldent really be called other than by the other register method
	 *  the names of classes include full namespace so its just easyer (and less error prone)
	 *  to pass (ClassName).class
	 */
	private void register(String key1,String key2,DispatchAction<T> action)
	{
		map.put(new DispatchPair(key1,key2), action);
	}
	
	/**
	 * Fires events based off the type of object 1 and object 2
	 *  if no action is applicable this method does nothing. 
	 *  The order of the objects dosen't matter
	 *  @return true if an event was fired false otherwise.
	 */
	@SuppressWarnings("unchecked") 
	public boolean fireEvent(Object obj1,Object obj2)
	{
		DispatchAction<T> action = map.get(new DispatchPair(obj1,obj2));
		if(action != null)
		{
			action.execute((T)obj1, (T)obj2);
			return true;
		}
		return false;
	}
	
	/**
	 *  Class is just a key-value pair container used to 
	 *  store classes as a group
	 * @author Andy
	 */
	private class DispatchPair
	{
		public String key1;
		public String key2;
		public DispatchPair(String key1,String key2)
		{
			this.key1 = key1;
			this.key2 = key2;
		}
		
		public DispatchPair(Object obj,Object obj2)
		{
			key1 = obj.getClass().getName();
			key2 = obj2.getClass().getName();
		}
		
		public boolean Equals(Object obj)
		{
			if(obj instanceof Dispatcher.DispatchPair)
			{
				DispatchPair other = ((DispatchPair)obj);
				if((other.key1 == key1 && other.key2 == key2) ||
				    other.key1 == key2 && other.key2 == key1)
					return true;
			}
			return false;
		}
	}
}


